package com.stlm2.controller.pay;


import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.pingplusplus.util.WxpubOAuth;
import com.stlm2.dems.entity.*;
import com.stlm2.dems.recharge.entity.Recharge;
import com.stlm2.dems.recharge.service.RechargeService;
import com.stlm2.dems.service.GoodsOrderService;
import com.stlm2.dems.service.PayConfigService;
import com.stlm2.dems.service.PurchaseOrderService;
import com.stlm2.dems.service.UserService;
import com.stlm2.util.DataSourceUtil;
import com.stlm2.util.codecontent.CodeContent;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;


/**
 * Author：fuchunyu
 * Date：2017/7/31
 * Description：微信支付
 */

@Controller
@RequestMapping("/wechat")
public class WechatPayController {

    @Resource
    private UserService userService;
    @Resource
    private RechargeService rechargeService;
    @Resource
    private PurchaseOrderService purchaseOrderService;
    @Resource
    private GoodsOrderService goodsOrderService;
    @Resource
    private PayConfigService payConfigService;

    /*微信流量支付*/

    @ResponseBody
    @RequestMapping("/rechargePay.json")
    public String pay(String companyCode,HttpServletRequest request, HttpServletResponse response, String openid,String phone, ModelMap model,String token, String money,String code,String fluxId,String flux) throws Exception {
        User user=userService.getByToken(token);
        System.out.println("companyCode:"+companyCode);
        PayConfig payConfig=payConfigService.getByCodeChannel(companyCode,PayChannel.Wechat);
        System.out.println("微信支付信息："+payConfig.getAppID()+","+payConfig.getKey()+","+payConfig.getMchID()+","+payConfig.getAppSecret());
        WXPay wxpay = new WXPay(payConfig, WXPayConstants.SignType.MD5, false);
        if(user==null){
            model.put("code", -1);
            model.put("msg", "用户未登陆");
            return new JSONObject(model).toString();
        }

        Recharge order=null;
        if(StringUtils.isEmpty(code)){
            order=rechargeService.addRecharge(user.getId(),money,Integer.parseInt(fluxId),Integer.parseInt(flux),phone);
        }else {
            order=rechargeService.getByCode(code);
        }

        System.out.println("进入微信支付openid："+openid);
        if (openid == null || openid.isEmpty()) {
            System.out.println("准备进入微信授权");
            try {
                String url = WxpubOAuth.createOauthUrlForCode(payConfig.getAppID(), "http://ddt.chinaddcat.com/wechat/weixinopenids?orderCode=" + order.getCode() + "&money=" + order.getMoney() + "&domain=" + request.getServerName()+"&companyCode="+companyCode+"&fluxId="+fluxId+"&phone="+phone+"&flux="+flux, false);
                System.out.println("返回的授权url"+url);
                model.put("code", 10);
                model.put("msg", "跳转到微信授权");
                model.put("url", url);
                return new JSONObject(model).toString();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "现金充值");
        data.put("out_trade_no", order.getCode());
        //data.put("device_info", "");
        data.put("fee_type", "CNY");
        data.put("total_fee", String.valueOf(order.getMoney().multiply(new BigDecimal(100)).intValue()));
        data.put("spbill_create_ip", request.getRemoteAddr());
        data.put("notify_url", "http://ddt.chinaddcat.com/wechat/rechargeNotify.json");
        data.put("trade_type", "JSAPI");
        data.put("product_id", order.getId().toString());
        data.put("openid", openid);
        data.put("attach", companyCode);
        System.out.println("total_fee:"+order.getMoney().multiply(new BigDecimal(100)).toString());
        Map<String, String> resp = null;
        try {
            System.out.println("发起支付");
            resp = wxpay.unifiedOrder(data);
            System.out.println(resp);
        } catch (Exception e) {
            e.printStackTrace();
        }

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String packages = "prepay_id="+resp.get("prepay_id");

        finalpackage.put("appId",  resp.get("appid"));
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", resp.get("nonce_str"));
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");

        String finalsign = WXPayUtil.generateSignature(finalpackage,payConfig.getKey());

        model.put("appid",  finalpackage.get("appId"));
        model.put("timeStamp", timestamp);
        model.put("nonceStr", finalpackage.get("nonceStr"));
        model.put("packageValue", packages);
        model.put("paySign", finalsign);
        model.put("code",1);



        return new JSONObject(model).toString();

    }
    /**
     * 提交支付后的微信异步返回接口
     */
    @RequestMapping("/rechargeNotify.json")
    public String rechargeNotify(String companyCode,HttpServletRequest request, HttpServletResponse response) throws Exception {
       /* WechatConfig config = new WechatConfig();
        WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5,true);*/


        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        String resultStr  = new String(outSteam.toByteArray(),"utf-8");

        Map<String, String> resultMap = WXPayUtil.xmlToMap(resultStr);
        String result_code = (String) resultMap.get("result_code");
        String is_subscribe = (String) resultMap.get("is_subscribe");
        String transaction_id = (String) resultMap.get("transaction_id");//微信支付订单号
        String sign = (String) resultMap.get("sign");
        String time_end = (String) resultMap.get("time_end");
        String bank_type = (String) resultMap.get("bank_type");

        String out_trade_no = (String) resultMap.get("out_trade_no");//商户订单号
        String return_code = (String) resultMap.get("return_code");//返回状态码
        String total_fee = (String) resultMap.get("total_fee");//订单金额
        String attach = (String) resultMap.get("attach");//商家数据包，原样返回
        System.out.println("商家数据包，原样返回："+attach);
        Boolean flag=DataSourceUtil.changeDataSource(attach);
        System.out.println("微信公众号回调切换数据源结果："+flag);
        PayConfig payConfig=payConfigService.getByCodeChannel(attach,PayChannel.Wechat);
        WXPay wxpay = new WXPay(payConfig, WXPayConstants.SignType.MD5, true);
        request.setAttribute("out_trade_no", out_trade_no);


        String notifyData = resultStr; // 支付结果通知的xml格式数据



        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        Map<String ,String> successMap=new HashMap<String, String>();
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            if(return_code.equals(WXPayConstants.SUCCESS)){
                System.out.println("微信SUCCESS");

                Recharge order=rechargeService.getByCode(out_trade_no);
                System.out.println("获取order"+order.getCode());
                if(order!=null){
                    if((Integer.parseInt(total_fee)/100)==order.getMoney().intValue()){
                        Recharge recharge = rechargeService.pay(order,transaction_id, PayChannel.wx_pub);
                        System.out.println("支付成功的recharge"+recharge.getOrderState().toString());
                        if(recharge.getOrderState().getIntValue()== OrderState.Payment.getIntValue()){
                            System.out.println("支付成功！！！！！，支付金额为："+total_fee+"，订单金额为："+order.getMoney().intValue());
                            successMap.put("return_code", "SUCCESS");
                            successMap.put("return_msg", "OK");
                            System.out.println(WXPayUtil.mapToXml(successMap));
                            response.setContentType("text/xml");
                            response.getWriter().write(WXPayUtil.mapToXml(successMap));
                        }
                    }
                }
                //支付成功的业务逻辑
            }else{
                System.out.println("支付失败！");
                //支付失败的业务逻辑
            }
            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
        }
        else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误
            System.out.println("签名错误！");
        }

        return resultStr;
    }



    /*微信商品支付*/
    /**
     * 用户提交支付，获取微信支付订单接口
     */
    @ResponseBody
    @RequestMapping(value = "/pay.json", produces = "application/json;charset=utf-8")
    public String pay(String companyCode,HttpServletRequest request, String openid, ModelMap model, String token, String code) throws Exception {
        User user = userService.getByToken(token);
        if (user == null)
            return CodeContent.returnLogin();
        if (StringUtils.isEmpty(code))
            return CodeContent.returnFailure("请重新发起支付！");
        PurchaseOrder purchaseOrder= purchaseOrderService.getByCode(code);
        if (purchaseOrder == null)
            return CodeContent.returnFailure("没有找到订单！");
        if (purchaseOrder.getUserId() - user.getId()!=0)
            return CodeContent.returnFailure("订单不匹配！");
        System.out.println("companyCode:"+companyCode);
        PayConfig payConfig=payConfigService.getByCodeChannel(companyCode,PayChannel.Wechat);
        System.out.println("微信支付信息："+payConfig.getAppID()+","+payConfig.getKey()+","+payConfig.getMchID()+","+payConfig.getAppSecret());
        WXPay wxpay = new WXPay(payConfig, WXPayConstants.SignType.MD5, false);

        System.out.println("进入微信支付openid：" + openid);
        if (openid == null || openid.isEmpty()) {
            System.out.println("准备进入微信授权");
            try {
                String url = WxpubOAuth.createOauthUrlForCode(payConfig.getAppID(), "http://ddt.chinaddcat.com/wechat/weixinopenid?orderCode=" + purchaseOrder.getCode() + "&money=" + purchaseOrder.getPayMoney() + "&domain=" + request.getServerName()+"&companyCode="+companyCode, false);
                System.out.println("返回的授权url" + url);
                model.put("code", 10);
                model.put("msg", "跳转到微信授权");
                model.put("url", url);
                return new JSONObject(model).toString();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        Map<String, String> data = new HashMap<String, String>();
        data.put("body", "叮当淘购买");
        data.put("out_trade_no", purchaseOrder.getCode());
        //data.put("device_info", "");
        data.put("fee_type", "CNY");
        System.out.println("无效的total fee?"+String.valueOf(purchaseOrder.getPayMoney().multiply(new BigDecimal(100)).intValue()));
        data.put("total_fee", String.valueOf(purchaseOrder.getPayMoney().multiply(new BigDecimal(100)).intValue()));
        data.put("spbill_create_ip", request.getRemoteAddr());
        data.put("notify_url", "http://ddt.chinaddcat.com/wechat/notify.json");
        data.put("trade_type", "JSAPI");
        data.put("product_id", purchaseOrder.getId().toString());
        data.put("openid", openid);
        data.put("attach", companyCode);
        System.out.println("attach"+data.get("attach"));
        Map<String, String> resp = null;
        try {
            System.out.println("发起支付");
            resp = wxpay.unifiedOrder(data);
            System.out.println(resp);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if(resp.get("return_code").equals(WXPayConstants.FAIL)){
            return CodeContent.returnFailure(resp.get("return_msg"));
        }

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        String packages = "prepay_id=" + resp.get("prepay_id");

        finalpackage.put("appId", resp.get("appid"));
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", resp.get("nonce_str"));
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");
        String finalsign = WXPayUtil.generateSignature(finalpackage, payConfig.getKey());

        model.put("appid", finalpackage.get("appId"));
        model.put("timeStamp", timestamp);
        model.put("nonceStr", finalpackage.get("nonceStr"));
        model.put("packageValue", packages);
        model.put("paySign", finalsign);
        model.put("code", 1);
        System.out.println(model.toString());


        return new JSONObject(model).toString();

    }

    @RequestMapping("/weixinopenid")
    public String weixinopenid(String companyCode,String code, String orderCode, String money, HttpServletResponse response) {
        System.out.println("进入微信授权");
        DataSourceUtil.changeDataSource(companyCode);
        PayConfig payConfig=payConfigService.getByCodeChannel(companyCode,PayChannel.Wechat);
        /*WXPay wxPay = new WXPay(payConfig);*/
        String openid;
        try {
            System.out.println("微信授权："+payConfig.getAppID()+","+payConfig.getAppSecret()+","+code);
            openid = WxpubOAuth.getOpenId(payConfig.getAppID(), payConfig.getAppSecret(), code);

            System.out.println("获取到的code:" + code + ",获取到的openid:" + openid);
            if (openid != null && !openid.isEmpty()) {
                try {
                    System.out.println("微信授权成功");
                    response.sendRedirect("http://ddt.chinaddcat.com/m/phoneHtml/choosePayWay.html?code=" + orderCode + "&payMoney=" + money + "&openid=" + openid);
                    response.flushBuffer();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("微信授权失败！");
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }

    @RequestMapping("/weixinopenids")
    public String weixinopenids(String companyCode,String code, String orderCode, String money, HttpServletResponse response,String flux,String fluxId,String phone) {
        System.out.println("进入微信授权");
        DataSourceUtil.changeDataSource(companyCode);
        PayConfig payConfig=payConfigService.getByCodeChannel(companyCode,PayChannel.Wechat);
        /*WXPay wxPay = new WXPay(payConfig);*/
        String openid;
        try {
            System.out.println("微信授权："+payConfig.getAppID()+","+payConfig.getAppSecret()+","+code);
            openid = WxpubOAuth.getOpenId(payConfig.getAppID(), payConfig.getAppSecret(), code);

            System.out.println("获取到的code:" + code + ",获取到的openid:" + openid);
            if (openid != null && !openid.isEmpty()) {
                try {
                    System.out.println("微信授权成功");
                    response.sendRedirect("http://ddt.chinaddcat.com/m/phoneHtml/flow_choosePayWay.html?code=" + orderCode + "&payMoney=" + money + "&openid=" + openid+ "&flux=" + flux+ "&fluxId=" + fluxId+ "&phone=" + phone);
                    response.flushBuffer();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("微信授权失败！");
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 提交支付后的微信异步返回接口
     */
    @RequestMapping("/notify.json")
    public void weixinNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("微信支付回调！");
        /*WechatConfig config = new WechatConfig();
        WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, true);*/


        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inStream.close();
        String resultStr = new String(outSteam.toByteArray(), "utf-8");
        System.out.println("微信支付回调返回结果："+resultStr);

        Map<String, String> resultMap = WXPayUtil.xmlToMap(resultStr);
        String result_code = (String) resultMap.get("result_code");
        String is_subscribe = (String) resultMap.get("is_subscribe");
        String transaction_id = (String) resultMap.get("transaction_id");//微信支付订单号
        String sign = (String) resultMap.get("sign");
        String time_end = (String) resultMap.get("time_end");
        String bank_type = (String) resultMap.get("bank_type");

        String out_trade_no = (String) resultMap.get("out_trade_no");//商户订单号
        String return_code = (String) resultMap.get("return_code");//返回状态码
        String total_fee = (String) resultMap.get("total_fee");//订单金额
        String attach = (String) resultMap.get("attach");//商家数据包，原样返回
        System.out.println("商家数据包，原样返回："+attach);
        Boolean flag=DataSourceUtil.changeDataSource(attach);
        System.out.println("微信公众号回调切换数据源结果："+flag);
        PayConfig payConfig=payConfigService.getByCodeChannel(attach,PayChannel.Wechat);
        WXPay wxpay = new WXPay(payConfig, WXPayConstants.SignType.MD5, true);
        request.setAttribute("out_trade_no", out_trade_no);


        String notifyData = resultStr; // 支付结果通知的xml格式数据

        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
        Map<String, String> successMap = new HashMap<String, String>();
        if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
            if (return_code.equals(WXPayConstants.SUCCESS)) {
                System.out.println("微信SUCCESS");

                PurchaseOrder order= purchaseOrderService.getByCode(out_trade_no);
                System.out.println("获取order" + order.getCode());
                if (order != null) {
                    if ((Integer.parseInt(total_fee) / 100) == order.getPayMoney().intValue()) {
                        PurchaseOrder  purchaseOrder = goodsOrderService.pay(order, PayChannel.wx_pub, transaction_id,attach);
                        System.out.println("支付成功的recharge" + purchaseOrder.getOrderState().toString());
                        if (purchaseOrder.getOrderState().getIntValue() == OrderState.Payment.getIntValue()) {
                            System.out.println("支付成功！！！！！，支付金额为：" + total_fee + "，订单金额为：" + order.getPayMoney().doubleValue());
                            successMap.put("return_code", "SUCCESS");
                            successMap.put("return_msg", "OK");
                            System.out.println(WXPayUtil.mapToXml(successMap));
                            response.setContentType("text/xml");
                            response.getWriter().write(WXPayUtil.mapToXml(successMap));
                        }
                    }
                }
                //支付成功的业务逻辑
            } else {
                System.out.println("支付失败！");
                //支付失败的业务逻辑
            }
            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
        } else {
            // 签名错误，如果数据里没有sign字段，也认为是签名错误
            System.out.println("签名错误！");
        }
    }

    /**
     * Author：fuchunyu
     * Date：2017/8/31
     * Description：微信对帐接口
     */
    @ResponseBody
    @RequestMapping("/test")
    public void test(String companyCode) throws Exception {

        WechatConfig config = new WechatConfig();
        WXPay wxpay = new WXPay(config, WXPayConstants.SignType.MD5, false);
        List<Recharge> list = rechargeService.getAll();
        for (Recharge recharge : list) {
            if (recharge.getTransactionNo() != null && recharge.getPayChannel().getIntValue() == 9) {
                Map<String, String> data = new HashMap<String, String>();
                data.put("transaction_id", recharge.getTransactionNo().trim());
                data.put("out_trade_no", recharge.getCode().trim());
                wxpay.fillRequestData(data);
                Map<String, String> resp = null;
                try {
                    resp = wxpay.orderQuery(data);
                    if (resp.get("trade_state").equals("SUCCESS") && resp.get("result_code").equals("SUCCESS") && resp.get("return_code").equals("SUCCESS")) {
                        int payMoney = Integer.parseInt(resp.get("cash_fee"));
                        int money = recharge.getMoney().intValue();
                        if ((payMoney / 100) != money) {
                            System.out.println("数据错误的ID：" + recharge.getId() + "，支付金额：" + payMoney + "，订单金额：" + money);
                            System.out.println(resp);
                        }
                    } else {
                        System.out.println("查询失败！" + recharge.getId());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}